const CELL_SIZE: usize = 128;
const OFFSET_COUNT: usize = 4;
const MAX_SIZE: usize = CELL_SIZE * OFFSET_COUNT;
// 4个 u128 构成的数组
#[derive(Debug, Default)]
pub(crate) struct Availability([u128; OFFSET_COUNT]);

impl Availability {
    pub(crate) fn avaliable(&self) -> bool {
        self.0.iter().any(|a| *a != 0)
    }

    pub(crate) fn get_available(&self, idx: usize) -> bool {
        let (offset, idx) = Self::offset(idx);
        self.0[offset] & (1 << idx as u128) != 0
    }

    pub(crate) fn set_available(&mut self, idx: usize, avail: bool) {
        let (offset, idx) = Self::offset(idx);
        // idx所在位置为1，其他为0
        let off = 1 << idx as u128;
        if avail {
            // 或运算，最终结果是在idx位置设置为1
            self.0[offset] |= off;
        } else {
            // 与运算，将off取反，如001，变成 110,再进行与运算，将特定位置设置为0
            self.0[offset] &= !off
        }
    }

    pub(crate) fn set_available_all(&mut self, ids: &[usize]) {
        ids.iter().for_each(|id| {
            self.set_available(*id, true);
        });
    }

    pub(crate) fn offset(idx: usize) -> (usize, usize) {
        if idx >= MAX_SIZE {
            panic!("Max WorkerHandle count is {}", MAX_SIZE)
        }
        let offset = idx / CELL_SIZE;
        let rdx = idx % CELL_SIZE;
        (offset, rdx)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    fn single(aval: &mut Availability, idx: usize) {
        aval.set_available(idx, true);
        assert_eq!(aval.avaliable(), true);
        assert_eq!(aval.get_available(idx), true);

        aval.set_available(idx, false);
        assert_eq!(aval.avaliable(), false);
        assert_eq!(aval.get_available(idx), false);
    }

    fn multi(aval: &mut Availability, idx: &[usize]) {
        idx.iter().for_each(|idx| aval.set_available(*idx, true));
        assert!(aval.avaliable());
        idx.iter().for_each(|idx| aval.set_available(*idx, false));
        assert_eq!(aval.avaliable(), false);
    }

    #[test]
    fn avaliable() {
        let mut ava = Availability::default();
        assert!(!ava.avaliable());
        single(&mut ava, 1);
        single(&mut ava, 129);
        single(&mut ava, 256);
        single(&mut ava, 511);

        let idx = (0..511).filter(|i| i % 3 == 0).collect::<Vec<usize>>();
        multi(&mut ava, &idx);
    }

    #[test]
    #[should_panic]
    fn overflow() {
        let mut aval = Availability::default();
        single(&mut aval, 512);
    }
    #[test]
    fn pin_point() {
        let mut aval = Availability::default();

        aval.set_available(438, true);

        aval.set_available(479, true);

        assert_eq!(aval.0[3], 1 << (438 - 384) | 1 << (479 - 384));
    }
}
